package com.un.ebs.sys.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.un.ebs.core.enums.PowerTypeEnum;
import com.un.ebs.core.util.SecurityUtils;
import com.un.ebs.core.util.StringUtils;
import com.un.ebs.sys.domain.*;
import com.un.ebs.sys.dto.AppRoleAddDto;
import com.un.ebs.sys.dto.AppRoleSetPowerDto;
import com.un.ebs.sys.dto.AppRoleSetRuleDto;
import com.un.ebs.sys.dto.AppRoleUpdateDto;
import com.un.ebs.sys.mapper.*;
import com.un.ebs.sys.service.AppRoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author liubo
 * @since 2019-09-15
 */
@Service
public class AppRoleServiceImpl extends ServiceImpl<AppRoleMapper, AppRole> implements AppRoleService {

    @Autowired
    private AppRolePowerMapper appRolePowerMapper;

    @Autowired
    private AppRoleRuleMapper appRoleRuleMapper;

    @Autowired
    private AppRolePowerDynamicMapper appRolePowerDynamicMapper;

    @Autowired
    private AppUserRoleMapper appUserRoleMapper;

    @Autowired
    private UserExtMapper userExtMapper;

    @Override
    public void add(AppRoleAddDto req) {
        AppRole obj = new AppRole();
        obj.setAppId(req.getAppId());
        obj.setCode(req.getCode());
        obj.setName(req.getName());
        obj.setHomepageUrl(req.getHomepageUrl());
        obj.setIsDelete(false);
        obj.setSort(0);
        obj.insert();
    }

    @Override
    public void update(AppRoleUpdateDto req) {
        // TODO: 2020/6/16 此处未考虑应用级的角色维护和租户级的角色维护，代码逻辑中没有区分 
        AppRole obj;
        if (StringUtils.isNullOrEmpty(req.getId())) {
            obj = new AppRole();
            obj.setSort(baseMapper.maxSort());
        } else {
            obj = getById(req.getId());
        }
        if (StringUtils.isNullOrEmpty(req.getAppId())) {
            obj.setAppId(SecurityUtils.getUserContent().getAppId());
        } else {
            obj.setAppId(req.getAppId());
        }
        obj.setCode(req.getCode());
        obj.setName(req.getName());
        obj.setHomepageUrl(req.getHomepageUrl());
        obj.insertOrUpdate();
    }

    @Override
    public AppRole queryById(String id) {
        return getBaseMapper().selectById(id);
    }

    @Override
    public List<String> queryIdByCode(List<String> codes) {
        LambdaQueryWrapper<AppRole> lq = Wrappers.lambdaQuery();
        lq.in(AppRole::getCode, codes);
        lq.eq(AppRole::getAppId, SecurityUtils.getUserContent().getAppId());
        return baseMapper.selectList(lq).stream().map(s -> s.getId()).distinct().collect(Collectors.toList());
    }

    @Override
    public List<UserExt> queryUserByRole(List<String> roleIds) {
        if (StringUtils.isNullOrEmpty(roleIds)) {
            return null;
        }
        LambdaQueryWrapper<AppUserRole> lq = Wrappers.lambdaQuery();
        lq.in(AppUserRole::getRoleId, roleIds);
        List<String> ids = appUserRoleMapper.selectList(lq).stream().map(s -> s.getUserId()).distinct().collect(Collectors.toList());

        if (ids == null) {
            return new ArrayList<>();
        }
        if (ids.size() <= 0) {
            return new ArrayList<>();
        }

        LambdaQueryWrapper<UserExt> query = Wrappers.lambdaQuery();
        query.in(UserExt::getId, ids);
        query.eq(UserExt::getTenantId, SecurityUtils.getTenantId());
        return userExtMapper.selectList(query);
    }

    @Override
    public void delete(String id) {
        getBaseMapper().deleteById(id);
    }

    @Override
    public void changeSort(String id, int index) {
        AppRole obj = getById(id);
        obj.setSort(index);
        getBaseMapper().updateById(obj);
    }

    @Transactional
    @Override
    public void setPower(String roleId, List<AppRoleSetPowerDto> list) {
        LambdaQueryWrapper<AppRolePower> lq = Wrappers.lambdaQuery();
        lq.eq(AppRolePower::getRoleId, roleId);
        appRolePowerMapper.delete(lq);
        for (AppRoleSetPowerDto dto : list) {
            AppRolePower obj = new AppRolePower();
            obj.setRoleId(roleId);
            obj.setPowerId(dto.getPowerId());
            obj.insert();
        }
    }

    @Override
    public void setResourcePower(String roleId, String resourceId, Boolean checked, PowerTypeEnum powerTypeEnum) {
        LambdaQueryWrapper<AppRolePowerDynamic> lq = Wrappers.lambdaQuery();
        lq.eq(AppRolePowerDynamic::getRoleId, roleId);
        lq.eq(AppRolePowerDynamic::getResourceId, resourceId);
        lq.eq(AppRolePowerDynamic::getPowerType, powerTypeEnum.getValue());
        if (checked) {
            AppRolePowerDynamic obj = appRolePowerDynamicMapper.selectOne(lq);
            if (obj == null) {
                obj = new AppRolePowerDynamic();
                obj.setRoleId(roleId);
                obj.setResourceId(resourceId);
                obj.setPowerType(powerTypeEnum.getValue());
                obj.insert();
            }
        } else {
            appRolePowerDynamicMapper.delete(lq);
        }
    }

    @Transactional
    @Override
    public void setRule(String roleId, List<AppRoleSetRuleDto> list) {
        LambdaQueryWrapper<AppRoleRule> lq = Wrappers.lambdaQuery();
        lq.eq(AppRoleRule::getRoleId, roleId);
        appRoleRuleMapper.delete(lq);
        for (AppRoleSetRuleDto dto : list) {
            AppRoleRule obj = new AppRoleRule();
            obj.setRoleId(roleId);
            obj.setRuleId(dto.getRuleId());
            obj.insert();
        }
    }

}